
#ifndef __LOGIC_MANAGER_H__
#define __LOGIC_MANAGER_H__

#include "Defines.h"

namespace nGameLogic
{
	struct sMSG_Restart;
}

class cEntity;
class cPlayerLogic;
class cStageManager;
class cMsgManager;
class cBullet;

struct sLogicManagerDesc
{
	sLogicManagerDesc()
	{
		parent = NULL;
	}

	CCNode* parent;
};

struct sCreateBulletArg
{
	sCreateBulletArg()
	{
		type = eBulletType::NORMAL;
		radius = 0.0f;
	}

	eBulletType::TYPE type;
	CCPoint pos;
	tFloat radius;
	tFilename spriteFilename;
};

struct sCreateEnemyArg
{
	sCreateEnemyArg()
	{
		type = eEnemyType::NORMAL; 
		foodID = 0;
		speed = 0.0f;
		radius = 0.0f;
	}

	eEnemyType::TYPE type;
	tInt foodID;
	CCPoint pos;
	tFloat speed;
	tFloat radius;
	tFilename spriteFilename;
};

struct sDetectCollisionArg
{
	sDetectCollisionArg()
	{
		distance = 0.0f;
		width = 0.0f;
		angle = 0.0f;
	}

	tFloat distance;
	tFloat width;
	tFloat angle;
	CCPoint playerPos;
	CCPoint direction;
};

struct sEntityDistanceInfo
{
	sEntityDistanceInfo()
	{
		entityID = INVALID_ID;
		distance = 0;
	}

	tBool operator < (const sEntityDistanceInfo& info)
	{
		return distance < info.distance;
	}

	tID entityID;
	tFloat distance;
};

typedef tList<sEntityDistanceInfo> tEntityDistanceInfoList;

class cLogicManager : public iMsgTargetBase, public b2ContactListener
{
	DECLARE_MSG_MAP()

public:
	cLogicManager();
	~cLogicManager();

	void Init(const sLogicManagerDesc& desc);
	void Update(tFloat dt);
	//void Draw();

	void Restart();
	void GameOver();
	void StageClear();

	tMsgTargetID GetMsgTargetID() const { return MSG_TARGET_LOGIC_MANAGER; }

	cBullet* CreateBullet(const sCreateBulletArg& arg);
	void CreateEnemy(const sCreateEnemyArg& arg);

	CCNode* GetSceneNode() const { return m_parent; }
	b2World* GetWorld() const { return m_b2World; }
	cPlayerLogic* GetPlayerLogic() const { return m_playerLogic; }
	cEntity* GetEntity(tID entityID);

	tInt GetStagePoint() const { return m_score; }
	void AddStagePointByEat(tInt eatCount);
	void SetStagePoint(tInt score);

	// logic
	void Shoot(const CCPoint& lastPos);
	void DetectCollision(const sDetectCollisionArg& arg, OUT tEntityDistanceInfoList& entityDistanceInfoList);

	// contact
	void BeginContact(b2Contact* contact);

private:
	void RemoveAllEntity();
	tID GenerateID() { return ++m_IDIssuer; }

	void Handle(const nGameLogic::sMSG_Restart& msg);

private:
	b2World* m_b2World;
	CCNode* m_parent;
	
	typedef map<tID, cEntity*> tEntityMap;
	tEntityMap m_entityMap;
	tID m_IDIssuer;

	cPlayerLogic* m_playerLogic;
	cStageManager* m_stageManager;

	// stage logic
	tBool m_gameOver;
	tInt m_score;
	cTimeCounter m_scoreTimer;
};


#endif // __LOGIC_MANAGER_H__

